/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFUserF1Task
  \brief user class for tasks of F1 data analysis
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2024-01-10
  \date 2024-01-10 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                    </tr>
  <tr>  <td>2024-01-10   <td>Asia Sun    <td>file created                   </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#include <algorithm>
#include <TFile.h>
#include <TTree.h>
#include <TClonesArray.h>
#include "ETFDetectorManager.h"
#include "ETFUserF1Task.h"
#include "ETFTimer4.h"
#include "ETFT0Array.h"
#include "ETFPlaHit.h"
#include "ETFHPTDCCh.h"
#include "ETFParaManager.h"
#include "ETFSource.h"
#include "ETFRun.h"
#include "ETFMsg.h"

using std::swap;

#define er ETFMsg::Error

ETFUserF1Task::ETFUserF1Task(const char *name) : ETFTask(name){}

ETFUserF1Task::~ETFUserF1Task(){}

void ETFUserF1Task::ETFUserF1Task::Configure(){
  ff1 = new TFile(ETFMsg::Form("f1_%s", fRun->GetRootFileName()), "RECREATE");
  f1 = new TTree("f1", "f1 data");

  fT0F1 = dynamic_cast<ETFTimer4 *>(fdm->GetDetector("tstart4"));
  fT0Arr = dynamic_cast<ETFT0Array *>(fdm->GetDetector("t0arr"));
  if(!fT0F1 || !fT0Arr) er("ETFUserF1Task", "Configure: nullptr for fT0F1 and/or fT0Arr");
  c0 = fT0F1->GetHits();
  carr = fT0Arr->GetHits();
} // end member function Configure

void ETFUserF1Task::CreateHistos(){
  Configure();

  f1->Branch("index", &index_, "index/I");
  f1->Branch("multi", &multi, "multi/I");
  f1->Branch("tlU", tlU, "tlU[multi][5]/D");
  f1->Branch("ttU", ttU, "ttU[multi][5]/D");
  f1->Branch("tlD", tlD, "tlD[multi][5]/D");
  f1->Branch("ttD", ttD, "ttD[multi][5]/D");
  f1->Branch("x_f1", x_f1, "x_f1[multi]/D");
  f1->Branch("t0lL", t0lL, "t0lL[5]/D");
  f1->Branch("t0tL", t0tL, "t0tL[5]/D");
  f1->Branch("t0lR", t0lR, "t0lR[5]/D");
  f1->Branch("t0tR", t0tR, "t0tR[5]/D");
  f1->Branch("t0lU", t0lU, "t0lU[5]/D");
  f1->Branch("t0tU", t0tU, "t0tU[5]/D");
  f1->Branch("t0lD", t0lD, "t0lD[5]/D");
  f1->Branch("t0tD", t0tD, "t0tD[5]/D");
} // end member function CreateHistos

void ETFUserF1Task::Exec(){
  Reset();
  index_ = fRun->Index();

  //----- T0Arr -----//
  multi = fT0Arr->multi();
  if(multi > 5) multi = 5; // exceeds the predefined max
  int nh = 0; // nof properly fired pla hits
  for(TObject *b : *carr){
    ETFPlaHit *h = dynamic_cast<ETFPlaHit *>(b);
    if(h->fired() != 4) continue; // not properly fired
    // up end
    const ETFHPTDCCh *hu = h->GetTChannel(0);
    const int nlu = hu->nl() < 5 ? hu->nl() : 5;
    for(int i = 0; i < nlu; i++) tlU[nh][i] = hu->tl(i);
    const int ntu = hu->nt() < 5 ? hu->nt() : 5;
    for(int i = 0; i < ntu; i++) ttU[nh][i] = hu->tt(i);
    // down end
    const ETFHPTDCCh *hd = h->GetTChannel(2);
    const int nld = hd->nl() < 5 ? hd->nl() : 5;
    for(int i = 0; i < nld; i++) tlD[nh][i] = hd->tl(i);
    const int ntd = hd->nt() < 5 ? hd->nt() : 5;
    for(int i = 0; i < ntd; i++) ttD[nh][i] = hd->tt(i);
    // strip position
    x_f1[nh] = h->x();
    if(++nh >= 5) break;
  } // end for over hits of T0Arr

  //----- T0F1 -----//
  const int nf1 = c0->GetEntriesFast();
  ETFPlaHit *hlr = nullptr, *hud = nullptr;
  if(nf1 >= 1) hlr = dynamic_cast<ETFPlaHit *>(c0->At(0));
  if(nf1 >= 2) hud = dynamic_cast<ETFPlaHit *>(c0->At(1));
  if((hlr && hlr->stripId() == 1) || (hud && hud->stripId() == 0)) swap(hlr, hud);
  if(hlr && hlr->fired() == 4){
    // left (outer) end
    const ETFHPTDCCh *hl = hlr->GetTChannel(0);
    const int nll = hl->nl() < 5 ? hl->nl() : 5;
    for(int i = 0; i < nll; i++) t0lL[i] = hl->tl(i);
    const int nlt = hl->nt() < 5 ? hl->nt() : 5;
    for(int i = 0; i < nlt; i++) t0tL[i] = hl->tt(i);
    // right (inner) end
    const ETFHPTDCCh *hr = hlr->GetTChannel(2);
    const int nrl = hr->nl() < 5 ? hr->nl() : 5;
    for(int i = 0; i < nrl; i++) t0lR[i] = hr->tl(i);
    const int nrt = hr->nt() < 5 ? hr->nt() : 5;
    for(int i = 0; i < nrt; i++) t0tR[i] = hr->tt(i);
  } // end if
  if(hud && hud->fired() == 4){
    // up end
    const ETFHPTDCCh *hu = hud->GetTChannel(0);
    const int nul = hu->nl() < 5 ? hu->nl() : 5;
    for(int i = 0; i < nul; i++) t0lU[i] = hu->tl(i);
    const int nut = hu->nt() < 5 ? hu->nt() : 5;
    for(int i = 0; i < nut; i++) t0tU[i] = hu->tt(i);
    // down end
    const ETFHPTDCCh *hd = hud->GetTChannel(2);
    const int ndl = hd->nl() < 5 ? hd->nl() : 5;
    for(int i = 0; i < ndl; i++) t0lD[i] = hd->tl(i);
    const int ndt = hd->nt() < 5 ? hd->nt() : 5;
    for(int i = 0; i < ndt; i++) t0tD[i] = hd->tt(i);
  } // end if

  f1->Fill();
} // end member function Exec

void ETFUserF1Task::Reset(){
  multi = -1;
  for(int i = 5; i--;){
    for(int j = 5; j--;){
      tlU[i][j] = ttU[i][j] = -999.;
      tlD[i][j] = ttD[i][j] = -999.;
    } // end for over j
    x_f1[i] = -999.;
    t0lL[i] = t0tL[i] = -999.;
    t0lR[i] = t0tR[i] = -999.;
    t0lU[i] = t0tU[i] = -999.;
    t0lD[i] = t0tD[i] = -999.;
  } // end for over i
} // end member function Reset

void ETFUserF1Task::WriteHistos(){
  ETFTask::WriteHistos();
  ff1->cd();
  f1->Write("", TObject::kOverwrite);
  ff1->Close();
} // end member fucntion WriteHistos
